// NOTE:this is an plugin for css/scss or other preprocessor to compile and hot module replace
import fp from "fastify-plugin";
import { FastifyInstance, FastifyRequest } from "fastify";
import path from "path";
import { ServerConfig } from "../config";
import { isCss } from "../utils";
import sass, { Result } from 'node-sass'

interface CssFastifyQuerystring {
  import: boolean;
}

const cssCacheMap = new Map<string, string>();

export default fp(async (instance: FastifyInstance, options: ServerConfig) => {
  instance.addHook(
    "preHandler",
    async (
      request: FastifyRequest<{
        Querystring: CssFastifyQuerystring;
      }>,
      reply
    ) => {
      const url = request.url.split("?")[0];
      if (isCss.test(url) && request.query.import !== undefined) {
        console.debug(`enter css plugin`, request.query);
        try {
          let compileStyleResult;
          if (cssCacheMap.has(url)) {
            compileStyleResult = cssCacheMap.get(url);
          } else {
            compileStyleResult = compileCss(url);
          }
          reply.type("application/javascript");
          return reply.send(genCssImportCode(url, compileStyleResult));
        } catch (e) {
          console.error(`[tserve css]:`, e);
          if (e.code === "ENOENT") {
            reply
              .code(404)
              .type("application/javascript")
              .send(`no such file: ${url}.`);
          } else {
            reply
              .code(500)
              .type("application/javascript")
              .send("error for reading css file");
          }
          return;
        }
      }
    }
  );
  instance.watcher.on("change", async (filePath: string) => {
    if (isCss.test(filePath)) {
      const url = path.join(options.root, filePath);
      compileCss(url);
      instance.esConnections.forEach((conn) => {
        const json = JSON.stringify({
          id: url,
        });
        conn.write(`event:css-update\ndata:${json}\n\n`);
      });
    }
  });

  // FIXME: repair compile scss import error;
  function compileCss(
    url: string,
  ): string {
    if (cssCacheMap.has(url)) {
      return cssCacheMap.get(url)!;
    }
    // const id =crypto.createHash("sha1").update(url).digest("hex").substr(0, 6) 
    const result: Result = sass.renderSync({
      file: path.resolve(process.cwd(), url.substring(1))
    }) 
    console.log(result)
    return result.css.toString();
  }
});

function genCssImportCode(id: string, code: string | undefined): string {
  return `import { updateStyle } from '/tserve/client.js'\n
          updateStyle('${id}',\`${code}\`)`;
}
